﻿#region

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

#endregion

namespace BlendHelpers
{
    public enum CommonStatesEnum
    {
        Normal = 0,
        MouseOver = 1,
        Pressed = 2,
        Disabled = 3
    }

    public enum CheckThreeStatesEnum
    {
        Unchecked = 0,
        Checked = 1,
        Indeterminate = 2
    }

    public enum CheckTwoStatesEnum
    {
        Unchecked = 0,
        Checked = 1
    }

    public enum FocusStatesEnum
    {
        Unfocused = 0,
        Focused = 1
    }

    public delegate void StateChangedEventHandler(string stateName);

    public class StatefulUserControlBase : UserControl
    {
        protected bool _isFocused;
        protected bool _isMouseOver;
        protected bool _isPressed;

        public StatefulUserControlBase()
        {
            IsEnabledChanged += StatefulUserControlBase_IsEnabledChanged;
            MouseEnter += UserControl_MouseEnter;
            MouseLeave += UserControl_MouseLeave;
            MouseLeftButtonDown += UserControl_MouseLeftButtonDown;
            MouseLeftButtonUp += UserControl_MouseLeftButtonUp;

            Loaded += StatefulUserControlBase_Loaded;
        }

        public virtual bool IsFocused
        {
            get { return _isFocused; }
            set
            {
                if (_isFocused == value) return;
                _isFocused = value;
                UpdateState();
            }
        }

        public event RoutedEventHandler Click;
        public event StateChangedEventHandler StateChanged;

        private void StatefulUserControlBase_Loaded(object sender, RoutedEventArgs e)
        {
            UpdateState();
        }

        private void StatefulUserControlBase_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            UpdateState();
        }

        protected virtual void UserControl_MouseEnter(object sender, MouseEventArgs e)
        {
            if (IsEnabled)
            {
                _isMouseOver = true;

                UpdateState();
            }
        }

        protected virtual void UserControl_MouseLeave(object sender, MouseEventArgs e)
        {
            if (IsEnabled)
            {
                _isPressed = false;
                _isMouseOver = false;

                UpdateState();
            }
        }

        protected virtual void UserControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (IsEnabled)
            {
                _isPressed = true;

                UpdateState();
            }
        }

        protected virtual void UserControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (IsEnabled)
            {
                _isPressed = false;

                if (Click != null) Click(this, new RoutedEventArgs());

                UpdateState();
            }
        }

        protected void InternalGoToState(string stateName)
        {
            bool b = VisualStateManager.GoToState(this, stateName, true);

            if (StateChanged != null)
                StateChanged(stateName);
        }

        protected virtual void UpdateState()
        {
            if (!IsEnabled)
            {
                InternalGoToState(CommonStatesEnum.Disabled.ToString());
            }
            else if (_isPressed)
            {
                InternalGoToState(CommonStatesEnum.Pressed.ToString());
            }
            else if (_isMouseOver)
            {
                InternalGoToState(CommonStatesEnum.MouseOver.ToString());
            }
            else
            {
                InternalGoToState(CommonStatesEnum.Normal.ToString());
            }

            if (_isFocused)
            {
                InternalGoToState(FocusStatesEnum.Focused.ToString());
            }
            else
            {
                InternalGoToState(FocusStatesEnum.Unfocused.ToString());
            }
        }
    }
}